<?php
/**
 * CRMLite Cron Table Class
 *
 * 配合 Zend_Cache 和 Zend_log 实现某一任务定时执行的效果
 *
 *
 * @package     Crmlite_Cron
 * @version     $Id: Cron.php 55 2007-09-09 12:44:28Z etng2004 $
 * @copyright   2006-2007 ETE.CN
 * @author      Yi BO  <etng2004@gmail.com>
 * @license     PHP Version 3.0 {@link http://www.php.net/license/3_0.txt}
 */
class Crmlite_Cron
{
    /**
     * Cache
     *
     * @var Zend_Cache_Core
     */
	protected $cache = null;
    /**
     * Zend_Log
     *
     * @var Zend_Log
     */
    protected $logger = null;
    /**
     * data
     *
     * @var array
     */
    protected $crons = array();
    /**
     * 缓存ID
     *
     * @var string
     */
    protected $cache_id = 'Crmlite_Cron';
    /**
     * 构造函数
     *
     * @param Zend_Cache_Core $cache
     * @param Zend_Log $logger
     */
	function __construct(Zend_Cache_Core $cache = null, Zend_Log $logger = null)
	{
        if($logger)$this->logger = $logger;
        if ($cache)
        {
            $this->cache = $cache;
        	$this->crons = $cache->load($this->cache_id);
        }
	}
	/**
	 * 判断是否存在该任务
	 *
	 * @param string $name
	 * @return bool
	 */
    function exists($name)
    {
    	return isset($this->crons[$name]);
    }
    /**
     * 注册一个定时任务
     *
     * @param string $name      任务名称
     * @param mixed $callback   任务回调函数
     * @param int $interval     任务执行频率
     * @param int $last_run     最后一次执行任务时间
     * @return bool             是否添加成功
     */
	function register($name, $callback, $interval, $last_run)
	{
	    if($this->exists($name))return false;
		$this->crons[$name] = array(
		'name'        => $name,
		'interval'    => $interval,
		'last_run'    => $last_run,
		'callback'    => $callback,
		);
		return true;
	}
	/**
	 * 取消任务
	 *
	 * @param string $name     任务名称
	 */
    function unregister($name)
    {
    	unset($this->crons[$name]);
    }
    /**
     * 清空任务列表
     *
     */
	function clear()
	{
		$this->crons = array();
	}
	/**
	 * 获得任务数量
	 *
	 * @return int
	 */
	function size()
	{
		return sizeof($this->crons);
	}

	/**
	 * 析构函数
	 *
	 * 执行各个定时任务，同时保存各个任务信息
	 *
	 */
	function __destruct()
	{
	    $current = time();
		foreach ($this->crons as $name => $cron)
		{
			if($current > $cron['last_run'] + $cron['interval'])
			{
			    $this->crons[$name]['last_run'] = $current;
			    call_user_func_array($cron['callback'], array($current, $this->logger));
			}
		}
		if($this->cache)$this->cache->save($this->crons, $this->cache_id);
	}
}

/**
 * Unit Testing
 */

if(basename(__FILE__) == $_SERVER['SCRIPT_FILENAME'])
{
    define('APPROOT', dirname(dirname(dirname(__FILE__))));
    set_include_path(APPROOT . '/lib/' . PATH_SEPARATOR . get_include_path());
    require_once 'Zend/Loader.php';
    Zend_Loader::registerAutoload();

    $logger = new Zend_Log(new Zend_Log_Writer_Stream( __FILE__ . '.debug.log' ));
	$logger->info(__FILE__);

	$cache = Zend_Cache::factory('Core', 'File', array('lifetime'=>null, 'automatic_serialization'=>true), array('cache_dir' => APPROOT . '/tmp/cache/'));

    $db = Zend_Db::factory('PDO_MYSQL', array(
    'host'  => 'localhost',
    'username'  => 'username',
    'password'  => 'password',
    'dbname'  => 'crmlite',
    'charset'  => 'utf8',
    ));
    $db->query('SET NAMES UTF8');

    $Cron = new Crmlite_Cron($cache, $logger);
    function cron_article_stat($time, $logger)
    {
        $logger->debug(__FUNCTION__ . ' called!');
    }
    function cron_links_stat($time, $logger)
    {
        $logger->debug(__FUNCTION__ . ' called!');
    }
    $Cron->register('cron_article_stat', 'cron_article_stat', 10, time());
    $Cron->register('cron_links_stat', 'cron_links_stat', 5, time());
}